import { saveAs } from 'file-saver';
import JSZip from 'jszip';
import dcmjs from 'dcmjs';
import * as nifti from 'nifti-reader-js';
import { createTdcAnnotationsData } from '../components/TDCMarkersPanel';

const { DicomMetaDictionary, DicomDict, DicomMessage } = dcmjs.data;

export class DicomExportService {
  static async exportProcessedResults(processedImages, originalMetadata, vesselMask = null, tdcMarkers = null, analysisInfo = null) {
    try {
      console.log('开始导出处理结果为DICOM和NIfTI文件...');
      
      const zip = new JSZip();
      const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
      
      // 创建子文件夹
      const dicomFolder = zip.folder('DICOM');
      const niftiFolder = zip.folder('NIfTI');
      const annotationsFolder = zip.folder('Annotations');
      
      // 为每个处理结果创建DICOM和NIfTI文件
      for (const [parameterName, parameterData] of Object.entries(processedImages)) {
        if (parameterData && parameterData.data) {
          console.log(`导出 ${parameterName.toUpperCase()} 参数图...`);
          
          // 创建DICOM文件
          const dicomArrayBuffer = await this.createDicomFromParameterData(
            parameterData, 
            parameterName.toUpperCase(), 
            originalMetadata,
            timestamp
          );
          
          const dicomFilename = `${parameterName.toUpperCase()}_${timestamp}.dcm`;
          dicomFolder.file(dicomFilename, dicomArrayBuffer);
          
          // 创建NIfTI文件
          const niftiArrayBuffer = this.createNiftiFromParameterData(
            parameterData,
            parameterName.toUpperCase(),
            originalMetadata
          );
          
          const niftiFilename = `${parameterName.toUpperCase()}_${timestamp}.nii`;
          niftiFolder.file(niftiFilename, niftiArrayBuffer);
        }
      }
      
      // 导出血管Mask为NIfTI文件（如果存在）
      if (vesselMask && vesselMask.mask) {
        console.log('导出血管Mask为NIfTI文件...');
        
        const vesselMaskNifti = this.createVesselMaskNifti(vesselMask, originalMetadata);
        const vesselMaskFilename = `VesselMask_${timestamp}.nii`;
        niftiFolder.file(vesselMaskFilename, vesselMaskNifti);
        
        console.log(`血管Mask导出完成: ${vesselMaskFilename}`);
      }
      
      // 导出TDC标记为LabelSetImage NIfTI文件（如果存在）
      if (tdcMarkers && tdcMarkers.length > 0) {
        console.log('导出TDC标记为LabelSetImage NIfTI文件...');
        
        // 获取图像尺寸（从处理结果或者原始数据获取）
        let imageWidth = 256, imageHeight = 256;
        const firstResult = Object.values(processedImages).find(p => p && p.data);
        if (firstResult) {
          imageWidth = firstResult.width || 256;
          imageHeight = firstResult.height || 256;
        }
        
        const labelSetNifti = this.createTdcMarkersLabelSetNifti(
          tdcMarkers, 
          imageWidth, 
          imageHeight, 
          originalMetadata
        );
        const labelSetFilename = `TDC_LabelSet_${timestamp}.nii`;
        niftiFolder.file(labelSetFilename, labelSetNifti);
        
        console.log(`TDC标记LabelSet导出完成: ${labelSetFilename}, 包含 ${tdcMarkers.length} 个标记`);
        
        // 导出TDC标注的JSON文件（如果存在）
        console.log('创建TDC标注JSON文件...');
        const jsonAnnotations = this.createTdcAnnotationsJson(
          tdcMarkers, 
          analysisInfo?.chartData || null,
          analysisInfo?.dicomData, 
          analysisInfo?.processingMethod, 
          analysisInfo?.arterialInputPoint,
          timestamp
        );
        
        const jsonFilename = `TDC_Annotations_${timestamp}.json`;
        annotationsFolder.file(jsonFilename, JSON.stringify(jsonAnnotations, null, 2));
        
        console.log(`TDC标注JSON文件导出完成: ${jsonFilename}`);
      }
      
      // 生成并下载ZIP文件
      const zipBlob = await zip.generateAsync({ type: 'blob' });
      const zipFilename = `DSA_ProcessingResults_${timestamp}.zip`;
      
      saveAs(zipBlob, zipFilename);
      console.log(`导出完成: ${zipFilename}`);
      
      return zipFilename;
    } catch (error) {
      console.error('导出DICOM和NIfTI文件失败:', error);
      throw new Error('导出失败: ' + error.message);
    }
  }

  static async createDicomFromParameterData(parameterData, parameterName, originalMetadata, timestamp) {
    try {
      const width = parameterData.width || 256;
      const height = parameterData.height || 256;
      
      // 使用原始数据而不是归一化数据 - 避免不必要的数组复制
      const pixelData = parameterData.originalData || parameterData.data;
      
      console.log(`${parameterName} 导出数据范围: ${parameterData.min} - ${parameterData.max} ${parameterData.units}`);
      
      // 创建伪彩色RGB数据用于DICOM
      const rgbData = this.createPseudoColorImage(pixelData, parameterData.min, parameterData.max);
      
      // 创建DICOM数据集
      const dataset = this.createDicomDataset(
        width,
        height,
        parameterName,
        originalMetadata,
        timestamp,
        rgbData,
        parameterData
      );
      
      // 使用dcmjs写入DICOM文件
      // 验证像素数据
      const meta = dataset._meta;
      const pixelDataObject = dataset.PixelData;
      delete dataset._meta;
      delete dataset.PixelData;

      // 添加调试信息
      console.log('PixelData调试信息:');
      console.log('- 类型:', typeof pixelDataObject);
      console.log('- 是否为ArrayBuffer:', pixelDataObject instanceof ArrayBuffer);
      console.log('- 字节长度:', pixelDataObject?.byteLength);
      console.log('- 构造函数:', pixelDataObject?.constructor?.name);

      // 确保pixelDataObject是有效的ArrayBuffer
      if (!(pixelDataObject instanceof ArrayBuffer)) {
        throw new Error(`PixelData不是ArrayBuffer，实际类型: ${typeof pixelDataObject}`);
      }

      // 检查并确保字节序正确（小端序）
      const uint8View = new Uint8Array(pixelDataObject);
      const isLittleEndian = new Uint8Array(new Uint16Array([0x1234]).buffer)[0] === 0x34;
      
      let finalPixelData = pixelDataObject;
      if (!isLittleEndian) {
        // RGB数据通常不需要字节序转换，但保留检查逻辑
        console.log('系统字节序检查完成');
      }

      // 使用基础方法创建DICOM文件
      const basicDataset = {
        _meta: meta,
        // 基本的图像信息
        PatientName: dataset.PatientName,
        PatientID: dataset.PatientID,
        StudyInstanceUID: dataset.StudyInstanceUID,
        SeriesInstanceUID: dataset.SeriesInstanceUID,
        SOPInstanceUID: dataset.SOPInstanceUID,
        SOPClassUID: dataset.SOPClassUID,
        Modality: dataset.Modality,
        Rows: dataset.Rows,  // 从原始数据集获取
        Columns: dataset.Columns,  // 从原始数据集获取
        BitsAllocated: 8,  // RGB图像使用8位
        BitsStored: 8,
        HighBit: 7,
        PixelRepresentation: 0,
        SamplesPerPixel: 3,  // RGB三个通道
        PhotometricInterpretation: 'RGB',  // RGB彩色图像
        PlanarConfiguration: 0,  // 像素交错存储
        
        // 图像类型和描述
        ImageType: dataset.ImageType || ['DERIVED', 'SECONDARY', 'OTHER'],
        
        // 其他重要信息
        StudyDate: dataset.StudyDate,
        StudyTime: dataset.StudyTime,
        SeriesDescription: dataset.SeriesDescription,
        AcquisitionDate: dataset.AcquisitionDate,
        AcquisitionTime: dataset.AcquisitionTime,
        ContentDate: dataset.ContentDate,
        ContentTime: dataset.ContentTime,
        
        // 图像定位和方向信息
        ImagePositionPatient: dataset.ImagePositionPatient || [0, 0, 0],
        ImageOrientationPatient: dataset.ImageOrientationPatient || [1, 0, 0, 0, 1, 0],
        PixelSpacing: dataset.PixelSpacing || [1, 1],
        SliceThickness: dataset.SliceThickness || '1',
        SliceLocation: dataset.SliceLocation || '0',
        
        // 设备信息
        Manufacturer: dataset.Manufacturer || 'DSA Image Processor',
        ManufacturerModelName: dataset.ManufacturerModelName || 'DSA Processing Software v2.0',
        SoftwareVersions: dataset.SoftwareVersions || 'DSA_PROCESSOR_V2.0_DCMJS',
        
        PixelData: finalPixelData
      };
      
      const basicDenaturalized = DicomMetaDictionary.denaturalizeDataset(basicDataset);
      const basicDict = new DicomDict(basicDenaturalized);
      const basicOutput = basicDict.write();
      
      console.log(`成功创建 ${parameterName} DICOM文件，大小: ${basicOutput.byteLength} 字节`);
      return basicOutput;
      
    } catch (error) {
      console.error(`创建${parameterName} DICOM文件失败:`, error);
      throw error;
    }
  }

  // 创建伪彩色RGB图像
  static createPseudoColorImage(grayData, minValue, maxValue) {
    const width = Math.sqrt(grayData.length);
    const height = width;
    const rgbDataSize = width * height * 3; // RGB三个通道
    const rgbBuffer = new ArrayBuffer(rgbDataSize);
    const rgbData = new Uint8Array(rgbBuffer);
    
    // 归一化范围
    const range = maxValue - minValue;
    
    for (let i = 0; i < grayData.length; i++) {
      let normalizedValue = 0;
      if (range > 0) {
        normalizedValue = Math.max(0, Math.min(1, (grayData[i] - minValue) / range));
      }
      
      // 使用jet transparent配色方案 (从深蓝色到红色的透明渐变)
      const rgb = this.valueToJetTransparentColormap(normalizedValue);
      
      const rgbIndex = i * 3;
      rgbData[rgbIndex] = rgb.r;     // Red
      rgbData[rgbIndex + 1] = rgb.g; // Green
      rgbData[rgbIndex + 2] = rgb.b; // Blue
    }
    
    console.log(`创建RGB数据: ${width}x${height}, 总字节数: ${rgbDataSize}`);
    return {
      buffer: rgbBuffer,
      width: width,
      height: height,
      channels: 3
    };
  }

  // Jet transparent配色方案：透明 -> 深蓝 -> 青色 -> 绿色 -> 黄色 -> 红色
  static valueToJetTransparentColormap(value) {
    // 限制值在0-1范围内
    value = Math.max(0, Math.min(1, value));
    
    // 当值为0时，返回黑色（透明效果）
    if (value === 0) {
      return { r: 0, g: 0, b: 0 };
    }
    
    let r, g, b;
    
    if (value < 0.125) {
      // 深蓝色
      r = 0;
      g = 0;
      b = Math.round(128 + 127 * (value / 0.125));
    } else if (value < 0.375) {
      // 深蓝到青色
      const t = (value - 0.125) / 0.25;
      r = 0;
      g = Math.round(255 * t);
      b = 255;
    } else if (value < 0.625) {
      // 青色到绿色
      const t = (value - 0.375) / 0.25;
      r = 0;
      g = 255;
      b = Math.round(255 * (1 - t));
    } else if (value < 0.875) {
      // 绿色到黄色
      const t = (value - 0.625) / 0.25;
      r = Math.round(255 * t);
      g = 255;
      b = 0;
    } else {
      // 黄色到红色
      const t = (value - 0.875) / 0.125;
      r = 255;
      g = Math.round(255 * (1 - t));
      b = 0;
    }
    
    return { r, g, b };
  }

  static createDicomDataset(width, height, parameterName, originalMetadata, timestamp, rgbData, parameterData) {
    const studyDate = timestamp.split('T')[0].replace(/-/g, '');
    const studyTime = timestamp.split('T')[1].split('.')[0].replace(/[-:]/g, '');
    
    // 生成唯一标识符
    const studyInstanceUID = this.generateUID();
    const seriesInstanceUID = this.generateUID();
    const sopInstanceUID = this.generateUID();
    
    console.log(`${parameterName} 图像尺寸: ${width}x${height}`);
    console.log(`${parameterName} RGB数据大小: ${rgbData.buffer.byteLength} 字节`);
    
    // 参数描述信息
    const parameterDescription = parameterData?.description || `${parameterName} Parameter Map`;
    const parameterUnits = parameterData?.units || 'unitless';
    
    const dataset = {
      // File Meta Information Group
      _meta: {
        FileMetaInformationVersion: new Uint8Array([0, 1]),
        MediaStorageSOPClassUID: '1.2.840.10008.5.1.4.1.1.7', // Secondary Capture Image Storage
        MediaStorageSOPInstanceUID: sopInstanceUID,
        TransferSyntaxUID: '1.2.840.10008.1.2', // Implicit VR Little Endian
        ImplementationClassUID: '1.2.276.0.7230010.3.0.3.6.7',
        ImplementationVersionName: 'DCMJS'
      },
      
      // Patient Information
      PatientName: originalMetadata?.patientName || 'DSA^PROCESSING',
      PatientID: originalMetadata?.patientId || 'DSA001',
      PatientBirthDate: originalMetadata?.patientBirthDate || '',
      PatientSex: originalMetadata?.patientSex || 'O',
      
      // Study Information
      StudyInstanceUID: studyInstanceUID,
      StudyID: originalMetadata?.studyId || 'DSA001',
      StudyDate: originalMetadata?.studyDate || studyDate,
      StudyTime: originalMetadata?.studyTime || studyTime,
      StudyDescription: `DSA Processing Results - ${parameterName}`,
      AccessionNumber: originalMetadata?.accessionNumber || '',
      
      // Series Information
      SeriesInstanceUID: seriesInstanceUID,
      SeriesNumber: 1,
      Modality: 'SC', // SC = Secondary Capture for processed images
      SeriesDescription: `${parameterDescription} (Pseudo-Color)`,
      
      // Image Information
      InstanceNumber: 1,
      SOPInstanceUID: sopInstanceUID,
      SOPClassUID: '1.2.840.10008.5.1.4.1.1.7', // Secondary Capture Image Storage
      ImageType: ['DERIVED', 'SECONDARY', 'OTHER'],
      
      // Image Pixel Module - RGB设置
      SamplesPerPixel: 3,
      PhotometricInterpretation: 'RGB',
      PlanarConfiguration: 0, // 0 = 像素交错 (RGBRGBRGB...)
      Rows: height,
      Columns: width,
      BitsAllocated: 8,
      BitsStored: 8,
      HighBit: 7,
      PixelRepresentation: 0, // 0 = unsigned
      
      // Image Position and Orientation
      ImageOrientationPatient: [1, 0, 0, 0, 1, 0],
      ImagePositionPatient: [0, 0, 0],
      PixelSpacing: [1, 1],
      SliceThickness: '1',
      SliceLocation: '0',
      
      // Equipment Information
      Manufacturer: 'DSA Image Processor',
      ManufacturerModelName: 'DSA Processing Software v2.0',
      SoftwareVersions: 'DSA_PROCESSOR_V2.0_DCMJS',
      InstitutionName: originalMetadata?.institutionName || 'Processing Center',
      
      // Content Information
      ContentDate: studyDate,
      ContentTime: studyTime,
      AcquisitionDate: studyDate,
      AcquisitionTime: studyTime,
      
      // Pixel Data - RGB数据
      PixelData: rgbData.buffer
    };
    
    return dataset;
  }

  static scaleDataToUint16(floatData) {
    // 找到数据的最大值和最小值
    let min = Infinity;
    let max = -Infinity;
    let validCount = 0;
    
    for (let i = 0; i < floatData.length; i++) {
      const value = floatData[i];
      if (!isNaN(value) && isFinite(value)) {
        if (value < min) min = value;
        if (value > max) max = value;
        validCount++;
      }
    }
    
    console.log(`数据缩放: 有效值=${validCount}/${floatData.length}, 范围=${min.toFixed(6)} - ${max.toFixed(6)}`);
    
    // 如果没有有效值
    if (validCount === 0) {
      console.warn('没有有效的数据值，填充为0');
      const uint16Data = new Uint16Array(floatData.length);
      uint16Data.fill(0);
      
      return {
        data: uint16Data,
        buffer: uint16Data.buffer,
        min: 0,
        max: 0,
        originalMin: 0,
        originalMax: 0,
        windowCenter: 0,
        windowWidth: 1
      };
    }
    
    // 如果所有值都相同
    if (min === max) {
      console.log('所有值都相同，映射到0');
      const constantValue = 0; // 映射到0，通过Rescale Intercept来处理真实值
      const uint16Data = new Uint16Array(floatData.length);
      uint16Data.fill(constantValue);
      
      return {
        data: uint16Data,
        buffer: uint16Data.buffer,
        min: constantValue,
        max: constantValue,
        originalMin: min,
        originalMax: max,
        windowCenter: constantValue,
        windowWidth: 1
      };
    }
    
    // 计算缩放参数
    const range = max - min;
    const scale = 65535 / range; // 使用全16位范围
    
    console.log(`数据缩放参数: 范围=${range.toFixed(6)}, 缩放因子=${scale.toFixed(6)}`);
    
    // 转换数据
    const uint16Data = new Uint16Array(floatData.length);
    for (let i = 0; i < floatData.length; i++) {
      const value = floatData[i];
      if (isNaN(value) || !isFinite(value)) {
        uint16Data[i] = 0; // 无效值设为0
      } else {
        const normalizedValue = (value - min) / range;
        uint16Data[i] = Math.round(normalizedValue * 65535);
      }
    }
    
    // 验证转换结果 - 使用循环避免栈溢出
    let convertedMin = Infinity;
    let convertedMax = -Infinity;
    for (let i = 0; i < uint16Data.length; i++) {
      const value = uint16Data[i];
      if (value < convertedMin) convertedMin = value;
      if (value > convertedMax) convertedMax = value;
    }
    console.log(`转换后的16位数据范围: ${convertedMin} - ${convertedMax}`);
    
    return {
      data: uint16Data,
      buffer: uint16Data.buffer,
      min: convertedMin,
      max: convertedMax,
      originalMin: min,
      originalMax: max,
      windowCenter: 32768,
      windowWidth: 65536
    };
  }

  static generateUID() {
    // 使用标准的DICOM UID格式
    const prefix = '1.2.826.0.1.3680043.9.7278.1'; // 示例前缀
    const timestamp = Date.now();
    const random = Math.floor(Math.random() * 1000000);
    return `${prefix}.${timestamp}.${random}`;
  }

  // 导出单个DICOM文件（不压缩）
  static async exportSingleDicom(parameterData, parameterName, originalMetadata) {
    try {
      const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
      
      const dicomArrayBuffer = await this.createDicomFromParameterData(
        parameterData,
        parameterName.toUpperCase(),
        originalMetadata,
        timestamp
      );
      
      const filename = `${parameterName.toUpperCase()}_${timestamp}.dcm`;
      const blob = new Blob([dicomArrayBuffer], { type: 'application/dicom' });
      
      saveAs(blob, filename);
      console.log(`单个DICOM文件导出完成: ${filename}`);
      
      return filename;
    } catch (error) {
      console.error('导出单个DICOM文件失败:', error);
      throw new Error('导出失败: ' + error.message);
    }
  }

  // 验证生成的DICOM文件
  static async validateDicomFile(arrayBuffer) {
    try {
      // 使用dcmjs解析生成的文件来验证
      const dicomData = DicomMessage.readFile(arrayBuffer);
      const dataset = DicomMetaDictionary.naturalizeDataset(dicomData.dict);
      
      console.log('DICOM文件验证成功:', {
        patientName: dataset.PatientName,
        studyDate: dataset.StudyDate,
        modality: dataset.Modality,
        rows: dataset.Rows,
        columns: dataset.Columns,
        bitsAllocated: dataset.BitsAllocated,
        windowCenter: dataset.WindowCenter,
        windowWidth: dataset.WindowWidth
      });
      
      return true;
    } catch (error) {
      console.error('DICOM文件验证失败:', error);
      return false;
    }
  }

  // 测试导出功能
  static async testExportFunction(processedImages, originalMetadata) {
    console.log('=== 开始测试DICOM导出功能 ===');
    
    try {
      // 找到第一个有效的处理结果进行测试
      const firstValidResult = Object.entries(processedImages).find(([key, value]) => value && value.data);
      
      if (!firstValidResult) {
        console.error('没有找到有效的处理结果');
        return;
      }
      
      const [parameterName, parameterData] = firstValidResult;
      console.log(`测试导出参数: ${parameterName}`, parameterData);
      
      // 创建测试DICOM文件
      const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
      const dicomArrayBuffer = await this.createDicomFromParameterData(
        parameterData,
        parameterName.toUpperCase(),
        originalMetadata,
        timestamp
      );
      
      console.log(`生成的DICOM文件大小: ${dicomArrayBuffer.byteLength} 字节`);
      
      // 验证文件
      const isValid = await this.validateDicomFile(dicomArrayBuffer);
      console.log(`DICOM文件验证结果: ${isValid ? '成功' : '失败'}`);
      
      // 下载测试文件
      const filename = `TEST_${parameterName.toUpperCase()}_${timestamp}.dcm`;
      const blob = new Blob([dicomArrayBuffer], { type: 'application/dicom' });
      saveAs(blob, filename);
      
      console.log(`测试文件已下载: ${filename}`);
      console.log('=== DICOM导出功能测试完成 ===');
      
    } catch (error) {
      console.error('测试导出功能失败:', error);
    }
  }

  // 测试scaleDataToUint16方法
  static testScaleDataToUint16() {
    console.log('=== 测试scaleDataToUint16方法 ===');
    
    // 创建一个模拟的参数数据（256x256 = 65536个像素）
    const testSize = 256 * 256;
    const testData = new Float32Array(testSize);
    
    // 填充测试数据
    for (let i = 0; i < testSize; i++) {
      testData[i] = Math.sin(i * 0.001) * 100 + 50; // 范围大约在-50到150之间
    }
    
    console.log(`测试数据大小: ${testData.length} 个像素`);
    
    try {
      const result = this.scaleDataToUint16(testData);
      console.log('scaleDataToUint16测试成功:', {
        originalMin: result.originalMin,
        originalMax: result.originalMax,
        convertedMin: result.min,
        convertedMax: result.max,
        bufferSize: result.buffer.byteLength
      });
      return true;
    } catch (error) {
      console.error('scaleDataToUint16测试失败:', error);
      return false;
    }
  }

  // 创建NIfTI文件
  static createNiftiFromParameterData(parameterData, parameterName, originalMetadata) {
    try {
      const width = parameterData.width || 256;
      const height = parameterData.height || 256;
      const depth = 1; // 单层图像
      
      // 使用原始浮点数据
      const pixelData = parameterData.originalData || parameterData.data;
      
      console.log(`${parameterName} NIfTI导出数据范围: ${parameterData.min} - ${parameterData.max} ${parameterData.units}`);
      
      // 创建NIfTI头部（348字节）
      const headerSize = 348;
      const header = new ArrayBuffer(headerSize);
      const headerView = new DataView(header);
      const headerUint8 = new Uint8Array(header);
      
      // NIfTI-1 header fields
      let offset = 0;
      
      // sizeof_hdr (4 bytes) - header size
      headerView.setInt32(offset, headerSize, true);
      offset += 4;
      
      // data_type (10 bytes) - unused
      offset += 10;
      
      // db_name (18 bytes) - unused
      offset += 18;
      
      // extents (4 bytes) - unused
      headerView.setInt32(offset, 16384, true);
      offset += 4;
      
      // session_error (2 bytes) - unused
      offset += 2;
      
      // regular (1 byte) - must be 'r'
      headerUint8[offset] = 'r'.charCodeAt(0);
      offset += 1;
      
      // dim_info (1 byte)
      headerUint8[offset] = 0;
      offset += 1;
      
      // dim[8] (16 bytes) - image dimensions
      headerView.setInt16(offset, 3, true); // ndim
      headerView.setInt16(offset + 2, width, true); // nx
      headerView.setInt16(offset + 4, height, true); // ny
      headerView.setInt16(offset + 6, depth, true); // nz
      headerView.setInt16(offset + 8, 1, true); // nt
      for (let i = 5; i < 8; i++) {
        headerView.setInt16(offset + i * 2, 1, true);
      }
      offset += 16;
      
      // intent_p1, intent_p2, intent_p3 (12 bytes)
      offset += 12;
      
      // intent_code (2 bytes)
      headerView.setInt16(offset, 0, true);
      offset += 2;
      
      // datatype (2 bytes) - 16 = float32
      headerView.setInt16(offset, 16, true);
      offset += 2;
      
      // bitpix (2 bytes) - bits per pixel
      headerView.setInt16(offset, 32, true);
      offset += 2;
      
      // slice_start (2 bytes)
      headerView.setInt16(offset, 0, true);
      offset += 2;
      
      // pixdim[8] (32 bytes) - pixel dimensions
      headerView.setFloat32(offset, -1.0, true); // qfac = -1 表示左手坐标系，修正Y轴方向
      headerView.setFloat32(offset + 4, 1.0, true); // pixel size x
      headerView.setFloat32(offset + 8, 1.0, true); // pixel size y
      headerView.setFloat32(offset + 12, 1.0, true); // pixel size z
      headerView.setFloat32(offset + 16, 1.0, true); // TR
      for (let i = 5; i < 8; i++) {
        headerView.setFloat32(offset + i * 4, 1.0, true);
      }
      offset += 32;
      
      // vox_offset (4 bytes) - data offset
      headerView.setFloat32(offset, headerSize, true);
      offset += 4;
      
      // scl_slope, scl_inter (8 bytes) - scaling parameters
      headerView.setFloat32(offset, 1.0, true); // slope
      headerView.setFloat32(offset + 4, 0.0, true); // intercept
      offset += 8;
      
      // slice_end (2 bytes)
      headerView.setInt16(offset, 0, true);
      offset += 2;
      
      // slice_code (1 byte)
      headerUint8[offset] = 0;
      offset += 1;
      
      // xyzt_units (1 byte) - spatial and temporal units
      headerUint8[offset] = 2; // mm
      offset += 1;
      
      // cal_max, cal_min (8 bytes) - calibration max/min
      headerView.setFloat32(offset, parameterData.max || 1.0, true);
      headerView.setFloat32(offset + 4, parameterData.min || 0.0, true);
      offset += 8;
      
      // slice_duration (4 bytes)
      headerView.setFloat32(offset, 0.0, true);
      offset += 4;
      
      // toffset (4 bytes)
      headerView.setFloat32(offset, 0.0, true);
      offset += 4;
      
      // glmax, glmin (8 bytes) - global max/min
      headerView.setInt32(offset, 0, true);
      headerView.setInt32(offset + 4, 0, true);
      offset += 8;
      
      // descrip (80 bytes) - description
      const description = `${parameterName} Parameter Map (${parameterData.units || 'unitless'})`;
      const descBytes = new TextEncoder().encode(description.substring(0, 79));
      headerUint8.set(descBytes, offset);
      offset += 80;
      
      // aux_file (24 bytes)
      offset += 24;
      
      // qform_code, sform_code (4 bytes)
      headerView.setInt16(offset, 2, true); // qform_code = 2 (aligned)
      headerView.setInt16(offset + 2, 2, true); // sform_code = 2 (aligned)
      offset += 4;
      
      // quatern_b, quatern_c, quatern_d (12 bytes) - 设置四元数表示Y轴翻转
      headerView.setFloat32(offset, 0.0, true); // quatern_b
      headerView.setFloat32(offset + 4, 1.0, true); // quatern_c - 180度绕Y轴旋转
      headerView.setFloat32(offset + 8, 0.0, true); // quatern_d
      offset += 12;
      
      // qoffset_x, qoffset_y, qoffset_z (12 bytes)
      headerView.setFloat32(offset, 0.0, true); // qoffset_x
      headerView.setFloat32(offset + 4, height - 1, true); // qoffset_y - Y轴偏移
      headerView.setFloat32(offset + 8, 0.0, true); // qoffset_z
      offset += 12;
      
      // srow_x, srow_y, srow_z (48 bytes) - affine transform
      // srow_x - 保持X轴不变
      headerView.setFloat32(offset, 1.0, true);
      headerView.setFloat32(offset + 4, 0.0, true);
      headerView.setFloat32(offset + 8, 0.0, true);
      headerView.setFloat32(offset + 12, 0.0, true);
      offset += 16;
      
      // srow_y - 翻转Y轴以修正上下颠倒问题
      headerView.setFloat32(offset, 0.0, true);
      headerView.setFloat32(offset + 4, -1.0, true); // 负值翻转Y轴
      headerView.setFloat32(offset + 8, 0.0, true);
      headerView.setFloat32(offset + 12, height - 1, true); // 偏移到图像底部
      offset += 16;
      
      // srow_z - 保持Z轴不变
      headerView.setFloat32(offset, 0.0, true);
      headerView.setFloat32(offset + 4, 0.0, true);
      headerView.setFloat32(offset + 8, 1.0, true);
      headerView.setFloat32(offset + 12, 0.0, true);
      offset += 16;
      
      // intent_name (16 bytes)
      const intentName = parameterName.substring(0, 15);
      const intentBytes = new TextEncoder().encode(intentName);
      headerUint8.set(intentBytes, offset);
      offset += 16;
      
      // magic (4 bytes) - NIfTI magic number
      const magic = new TextEncoder().encode('n+1\0');
      headerUint8.set(magic, offset);
      
      // 创建像素数据（32位浮点）
      const pixelDataSize = width * height * depth * 4; // 4 bytes per float32
      const pixelDataBuffer = new ArrayBuffer(pixelDataSize);
      const pixelDataView = new Float32Array(pixelDataBuffer);
      
      // 复制像素数据 - 同时翻转Y轴
      console.log(`开始复制和翻转像素数据: ${width}x${height}`);
      for (let y = 0; y < height; y++) {
        for (let x = 0; x < width; x++) {
          const srcIndex = y * width + x;
          const dstIndex = (height - 1 - y) * width + x; // 翻转Y坐标
          pixelDataView[dstIndex] = pixelData[srcIndex];
        }
      }
      console.log(`像素数据翻转完成`);
      
      // 合并头部和数据
      const totalSize = headerSize + pixelDataSize;
      const niftiBuffer = new ArrayBuffer(totalSize);
      const niftiUint8 = new Uint8Array(niftiBuffer);
      
      niftiUint8.set(new Uint8Array(header), 0);
      niftiUint8.set(new Uint8Array(pixelDataBuffer), headerSize);
      
      console.log(`成功创建 ${parameterName} NIfTI文件，大小: ${niftiBuffer.byteLength} 字节`);
      return niftiBuffer;
      
    } catch (error) {
      console.error(`创建${parameterName} NIfTI文件失败:`, error);
      throw error;
    }
  }

  // 创建血管Mask的NIfTI文件（复用参数图NIfTI创建逻辑）
  static createVesselMaskNifti(vesselMask, originalMetadata) {
    try {
      const { mask, width, height } = vesselMask;
      
      console.log(`血管Mask NIfTI导出: ${width}x${height}, 血管像素: ${vesselMask.stats?.vesselPixels || 'unknown'}`);
      
      // 将mask数据转换为Float32Array以复用参数图的逻辑
      const maskFloatData = new Float32Array(mask.length);
      for (let i = 0; i < mask.length; i++) {
        maskFloatData[i] = mask[i]; // 0或1转换为浮点数
      }
      
      // 创建模拟的参数数据对象
      const parameterData = {
        data: maskFloatData,
        originalData: maskFloatData,
        width: width,
        height: height,
        units: 'binary',
        description: 'Vessel Mask - Binary segmentation of vessel regions',
        min: 0,
        max: 1
      };
      
      // 直接复用参数图的NIfTI创建逻辑
      return this.createNiftiFromParameterData(parameterData, 'VesselMask', originalMetadata);
      
    } catch (error) {
      console.error('创建血管Mask NIfTI文件失败:', error);
      throw error;
    }
  }

  // 创建TDC标记的LabelSetImage NIfTI文件（复用参数图NIfTI创建逻辑）
  static createTdcMarkersLabelSetNifti(tdcMarkers, imageWidth, imageHeight, originalMetadata) {
    try {
      console.log(`TDC标记LabelSet NIfTI导出: ${imageWidth}x${imageHeight}, 标记数量: ${tdcMarkers.length}`);
      
      // 创建标签图像数据（每个像素存储标记ID）
      const labelData = new Uint16Array(imageWidth * imageHeight);
      labelData.fill(0); // 背景标签为0
      
      // 将每个可见的标记转换为标签区域
      const visibleMarkers = tdcMarkers.filter(marker => marker.visible !== false);
      visibleMarkers.forEach((marker, index) => {
        const labelValue = index + 1; // 标签值从1开始
        
        if (marker.type === 'point') {
          // 点标记：创建一个小的十字形区域
          const centerX = Math.round(marker.x);
          const centerY = Math.round(marker.y);
          const radius = 2; // 十字形半径
          
          for (let dy = -radius; dy <= radius; dy++) {
            for (let dx = -radius; dx <= radius; dx++) {
              if (Math.abs(dx) <= 1 || Math.abs(dy) <= 1) { // 十字形
                const x = centerX + dx;
                const y = centerY + dy;
                if (x >= 0 && x < imageWidth && y >= 0 && y < imageHeight) {
                  const index = y * imageWidth + x;
                  labelData[index] = labelValue;
                }
              }
            }
          }
          
        } else if (marker.type === 'region') {
          // 矩形区域标记
          const region = marker.region;
          const startX = Math.max(0, Math.floor(region.x));
          const endX = Math.min(imageWidth, Math.ceil(region.x + region.width));
          const startY = Math.max(0, Math.floor(region.y));
          const endY = Math.min(imageHeight, Math.ceil(region.y + region.height));
          
          for (let y = startY; y < endY; y++) {
            for (let x = startX; x < endX; x++) {
              const index = y * imageWidth + x;
              labelData[index] = labelValue;
            }
          }
          
        } else if (marker.type === 'contour') {
          // 轮廓标记：使用射线法填充轮廓内部
          const contour = marker.contour;
          if (contour.path && contour.path.length >= 3) {
            const bounds = contour.bounds;
            const startX = Math.max(0, Math.floor(bounds.minX));
            const endX = Math.min(imageWidth, Math.ceil(bounds.maxX));
            const startY = Math.max(0, Math.floor(bounds.minY));
            const endY = Math.min(imageHeight, Math.ceil(bounds.maxY));
            
            for (let y = startY; y < endY; y++) {
              for (let x = startX; x < endX; x++) {
                if (this.isPointInPolygon({ x, y }, contour.path)) {
                  const index = y * imageWidth + x;
                  labelData[index] = labelValue;
                }
              }
            }
          }
        }
      });
      
      // 计算标签统计
      const labelStats = {};
      for (let i = 0; i < labelData.length; i++) {
        const label = labelData[i];
        labelStats[label] = (labelStats[label] || 0) + 1;
      }
      console.log('标签统计:', labelStats);
      
      // 将标签数据转换为Float32Array以复用参数图的逻辑
      const labelFloatData = new Float32Array(labelData.length);
      for (let i = 0; i < labelData.length; i++) {
        labelFloatData[i] = labelData[i]; // 标签值转换为浮点数
      }
      
      // 创建模拟的参数数据对象
      const parameterData = {
        data: labelFloatData,
        originalData: labelFloatData,
        width: imageWidth,
        height: imageHeight,
        units: 'labels',
        description: `TDC Markers LabelSet - ${visibleMarkers.length} ROI labels`,
        min: 0,
        max: visibleMarkers.length
      };
      
      // 直接复用参数图的NIfTI创建逻辑
      return this.createNiftiFromParameterData(parameterData, 'TDC_LabelSet', originalMetadata);
      
    } catch (error) {
      console.error('创建TDC标记LabelSet NIfTI文件失败:', error);
      throw error;
    }
  }

  // 辅助函数：判断点是否在多边形内部（射线法）
  static isPointInPolygon(point, polygon) {
    const { x, y } = point;
    let isInside = false;
    
    for (let i = 0, j = polygon.length - 1; i < polygon.length; j = i++) {
      const xi = polygon[i].x;
      const yi = polygon[i].y;
      const xj = polygon[j].x;
      const yj = polygon[j].y;
      
      if (((yi > y) !== (yj > y)) && (x < (xj - xi) * (y - yi) / (yj - yi) + xi)) {
        isInside = !isInside;
      }
    }
    
    return isInside;
  }

  // 创建TDC标注的JSON文件 - 使用TDCMarkersPanel的功能
  static createTdcAnnotationsJson(tdcMarkers, chartData, dicomData, processingMethod, arterialInputPoint, timestamp) {
    if (!dicomData || !tdcMarkers) {
      console.warn('缺少必要数据，无法创建TDC标注JSON');
      return null;
    }

    try {
      console.log('使用TDCMarkersPanel功能创建完整的TDC标注JSON...');
      
      // 使用TDCMarkersPanel的createTdcAnnotationsData函数，它包含完整的统计计算功能
      const jsonData = createTdcAnnotationsData(
        tdcMarkers,
        chartData,
        dicomData,
        processingMethod,
        arterialInputPoint
      );

      console.log('TDC标注JSON创建完成，包含', tdcMarkers.length, '个标记，包含完整的TDC统计参数');
      return jsonData;
    } catch (error) {
      console.error('创建TDC标注JSON失败:', error);
      
      // 如果使用TDCMarkersPanel功能失败，回退到基础实现
      console.warn('回退到基础TDC标注JSON实现...');
      try {
        const basicJsonData = {
          exportInfo: {
            timestamp: new Date().toISOString(),
            version: '1.0',
            description: 'TDC分析标注结果（基础版本）',
            totalMarkers: tdcMarkers.length,
            visibleMarkers: tdcMarkers.filter(m => m.visible !== false).length,
            processingMethod: processingMethod || 'normal',
            arterialInputPoint: arterialInputPoint ? {
              x: arterialInputPoint.x,
              y: arterialInputPoint.y,
              description: '最大斜率法使用的动脉输入点'
            } : null,
            note: '由于计算错误，此版本不包含完整的TDC统计参数'
          },
          imageInfo: {
            totalFrames: dicomData.images?.length || 0,
            imageSize: dicomData.images?.[0] ? {
              width: dicomData.images[0].columns || dicomData.images[0].width,
              height: dicomData.images[0].rows || dicomData.images[0].height
            } : null,
            studyUID: dicomData.images?.[0]?.studyInstanceUID || dicomData.metadata?.studyInstanceUID || 'N/A',
            seriesUID: dicomData.images?.[0]?.seriesInstanceUID || dicomData.seriesInstanceUID || 'N/A'
          },
          annotations: tdcMarkers.map(marker => {
            const annotation = {
              id: marker.id,
              name: marker.name,
              type: marker.type,
              color: marker.color,
              visible: marker.visible !== false,
              coordinates: null,
              note: '基础版本，不包含TDC计算参数'
            };

            // 添加坐标信息
            if (marker.type === 'point') {
              annotation.coordinates = { x: marker.x, y: marker.y };
            } else if (marker.type === 'region') {
              annotation.coordinates = {
                x: marker.region.x,
                y: marker.region.y,
                width: marker.region.width,
                height: marker.region.height
              };
            } else if (marker.type === 'contour') {
              annotation.coordinates = {
                path: marker.contour.path,
                bounds: marker.contour.bounds
              };
            }

            return annotation;
          })
        };

        console.log('基础TDC标注JSON创建完成');
        return basicJsonData;
      } catch (fallbackError) {
        console.error('基础实现也失败:', fallbackError);
        return null;
      }
    }
  }
}

// 将测试函数暴露到全局作用域
window.testDicomExport = DicomExportService.testExportFunction.bind(DicomExportService);
window.testScaleDataToUint16 = DicomExportService.testScaleDataToUint16.bind(DicomExportService);